package com.apes.fn.scm.retailOrder.service.account.retail;

import com.apes.fn.scm.retailOrder.model.RetailOrder;
import com.apes.fn.scm.retailOrder.model.RetailOrderItem;
import com.apes.fn.scm.retailOrder.service.account.BackBatchAndSupplierService;
import com.apes.fn.scm.retailOrder.service.account.RetailAccountData;
import com.apes.framework.util.MapUtil;
import com.apes.framework.util.ReflectUtil;
import com.apes.scm.account.tax.model.Tax;
import com.apes.scm.account.tax.service.TaxService;
import com.apes.scm.contract.model.Contract;
import com.apes.scm.contract.service.ContractService;
import com.apes.scm.masterdata.party.model.PartyRole;
import com.apes.scm.masterdata.party.repository.PartyRoleRepository;
import com.apes.scm.voucher.model.Voucher;
import com.apes.scm.voucher.model.VoucherInventory;
import com.apes.scm.voucher.model.VoucherItem;
import com.apes.scm.voucher.repository.VoucherInventoryRepository;
import com.apes.scm.voucher.service.BusinessType;
import com.apes.scm.voucher.service.VoucherType;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * 年审带安逻辑处理
 *
 * @Author wuq
 * @Date 2021-9-13
 */
@RetailAccount(value = "annualAudit", name = "年审带安")
@Service
public class AnnualAuditVoucherService extends BackBatchAndSupplierService {

    @Autowired
    private TaxService taxService;
    @Autowired
    private ContractService contractService;
    @Autowired
    private PartyRoleRepository partyRoleRepository;
    @Autowired
    private VoucherInventoryRepository voucherInventoryRepository;

    /**
     * 外协代销带安逻辑处理
     * 代销模式（寄售模式）：在寄售采购与寄售销售的时候，不写账单（销售的部分只是冻结批次），在实现销售的时候，根据寄售消耗凭证写账单
     *
     * @param retailAccountData RetailOrder
     */
    public void process(RetailAccountData retailAccountData) {
        RetailOrder retailOrder = retailAccountData.getRetailOrder();

        // 带安
        Map<String, List<RetailOrderItem>> outRetailOrderItems = retailOrder.getSaleItems()
                .stream()
                .filter( item -> item.getProductRule() == 10 && item.getSupplier() != null)
                .collect(Collectors.groupingBy(x -> x.getSupplier().getId() + ";" + x.getPlatform().getId()));

        outRetailOrderItems.forEach( (unique, retailOrderItems) -> {
            String[] uniques = unique.split(";");
            String platformId = uniques[1];    // 平台公司
            PartyRole supplier = retailOrderItems.get(0).getSupplier().getParty().getPartyRoleByType("Supplier");


            if ( "1001".equals(platformId) && platformId.equals(retailOrder.getCompany().getId()) ) {
                // 1001 平台， 直接找供应商采购(直营门店)，1001 对供应商的采购合同
                Contract contract = contractService.getContract(retailOrder.getDept(), supplier, "consignment", "supplier", "零售年审业务");
                createOutPurchaseVoucher(retailOrder, contract, retailOrderItems, false);
            }

            if ( "1001".equals(platformId) && !platformId.equals(retailOrder.getCompany().getId()) ) {
                // 1001 平台， 找 1001 做采购（佛山车宝，志运门店），1001 对供应商的采购合同
                PartyRole platformCompany = partyRoleRepository.findOne(platformId);
                Contract contract = contractService.getContract(getDept(platformCompany), supplier, "consignment", "supplier", "零售年审业务");
                createOutCrossPurchaseVoucher(retailOrder, contract, retailOrderItems);
            }

            if ( "1007".equals(platformId) ) {
                // 1007 平台，查询平台协议
               List<Contract> contracts = contractService.getContract(VoucherType.PLATFORM_CODE, supplier.getId());
                Contract contract = contracts.stream()
                        .filter(c -> "platform".equals(c.getContractType().getCode()))
                        .findFirst()
                        .orElseThrow(()-> new RuntimeException(String.format("没有找到供应商 [ %s ] ，对应的[ %s ] 平台合同", supplier.getId(), VoucherType.PLATFORM_CODE)));
                createOutPurchaseVoucher(retailOrder, contract, retailOrderItems, false);
            }
        });
    }

    /**
     * isCross
     *      true:  对合同公司采购
     *      false: 对外部供应商采购
     *
     * @param retailOrder 零售单
     * @param contract    合同
     * @param items       零售单明细
     * @param isCross     是否跨公司
     */
    private void createOutPurchaseVoucher(RetailOrder retailOrder, Contract contract, List<RetailOrderItem> items, boolean isCross) {
        Voucher purVoucher = new Voucher();
        ReflectUtil.copy(retailOrder, purVoucher, "dept", "company", "scene");

        if (isCross) {  // 如果是跨公司，就需要找合同上面的公司做采购；非跨公司，就直接找真实供应商采购
            PartyRole supplier = contract.getCompany().getParty().getPatyRoleByType("Supplier");
            purVoucher.setPartner(supplier);
            Contract innerContract = contractService.getContract(retailOrder.getDept(), supplier, "distribution", "supplier", "零售年审业务");
            purVoucher.setContract(innerContract);
        } else {
            // 直接对外部供应商采购为 代销
            purVoucher.setContract(contract);
            purVoucher.setPartner(contract.getPartner().getParty().getPatyRoleByType("Supplier"));
        }

        purVoucher.setInventoryMode(purVoucher.getContract().getCooperation().getInventoryMode());     //设置库存模式：寄售
        purVoucher.setAccountingMethod(purVoucher.getContract().getCooperation().getAccountingMethod());  // 核算方式：采购价
        purVoucher.setClassification(VoucherType.CONSIGNMENT_INSTALL);
        purVoucher.setCustomerExpand(retailOrder.getCustomerExpand().getId());
        purVoucher.setClerk(retailOrder.getClerk()); //业务员

        purVoucher.setBusinessType(BusinessType.PURCHASE_ORDER);
        purVoucher.setOrigin(retailOrder.getId());
        purVoucher.setOriginBusinessType(retailOrder.getInnerBusinessType());
        purVoucher.setSource(retailOrder.getId());
        purVoucher.setSourceBusinessType(retailOrder.getInnerBusinessType());

        PartyRole supplier = purVoucher.getPartner();
        purVoucher.setVoucherItems(
                items.stream().map(
                        item -> {
                            VoucherItem voucherItem = new VoucherItem();

                            ReflectUtil.copy(item, voucherItem, "product", "uom");
                            voucherItem.setOwner(item.getOwner());

                            voucherItem.setInnerSalePriceUnit(item.getInnerSalePriceUnit());    // 公司间交易价
                            voucherItem.setPriceUnit(item.getInnerSalePriceUnit());     // 内部销售价
                            voucherItem.setProductQty(item.getProductUomQty());
                            voucherItem.setInventoryBatch(item.getInventoryBatch());    // 指定销售批次

                            voucherItem.setOriginItemId(item.getId());
                            voucherItem.setSourceItemId(item.getId());
                            voucherItem.setSupplier(item.getSupplier());
                            voucherItem.setOwner(retailOrder.getCompany());

                            voucherItem.setDiscount(0d);
                            Tax tax = taxService.getPurchaseTax(retailOrder.getCompany(), supplier, item.getProduct());   //供应商进项税
                            voucherItem.setTax(tax);
                            return voucherItem;
                        }
                ).collect(Collectors.toSet()));
        if (purVoucher.getVoucherItems().size() == 0) throw new RuntimeException("生成带安采购凭证时报错，没有采购凭证明细！");

        purVoucher = invoke("voucher.create", MapUtil.mapped(purVoucher));

        // 回写方案明细批次以及供应商信息
        sendRetailBathAndSupplier(items, purVoucher);

        // 存在内部销售为经销的，需要写账单
        if ("IM_OWN".equals(purVoucher.getInventoryMode())) {
            invoke("invoice.create", MapUtil.mapped(invoke("voucher.flow.invoice", MapUtil.mapped(purVoucher))));
        }
    }


    private void createOutCrossPurchaseVoucher(RetailOrder retailOrder, Contract contract, List<RetailOrderItem> items) {
        // 合同公司采购以及销售
        Voucher voucher = createCrossPurchaseVoucher(retailOrder, contract, items);
        createCrossSaleVoucher(voucher, items);

        // 对合同上面的公司生成带安采购凭证
        createOutPurchaseVoucher(retailOrder, contract, items, true);
    }

    /**
     * 合同公司对外部供应的采购凭证
     *
     * @param retailOrder      零售单
     * @param purContract      采购合同
     * @param retailOrderItems 零售单明细
     * @return Voucher
     */
    private Voucher createCrossPurchaseVoucher(RetailOrder retailOrder, Contract purContract, List<RetailOrderItem> retailOrderItems) {
        Voucher purVoucher = new Voucher();
        purVoucher.setBusinessType(BusinessType.PURCHASE_ORDER);
        purVoucher.setClerk(retailOrder.getClerk()); //业务员

        purVoucher.setDept(purContract.getDept());
        purVoucher.setCompany(purContract.getCompany());
        purVoucher.setPartner(purContract.getPartner().getParty().getPartyRoleByType("Supplier"));     // 外部供应商

        // 这里为代销采购
        purVoucher.setContract(purContract);
        purVoucher.setCustomerExpand(retailOrder.getCustomerExpand().getId());

        purVoucher.setOrigin(retailOrder.getId());
        purVoucher.setOriginBusinessType(retailOrder.getInnerBusinessType());
        purVoucher.setSource(retailOrder.getId());
        purVoucher.setSourceBusinessType(retailOrder.getInnerBusinessType());

        purVoucher.setInventoryMode(purVoucher.getContract().getCooperation().getInventoryMode());     // 库存模式
        purVoucher.setAccountingMethod(purVoucher.getContract().getCooperation().getAccountingMethod());  // 核算方

        purVoucher.setVoucherItems(
                retailOrderItems.stream().map(
                        item -> {
                            VoucherItem voucherItem = new VoucherItem();
                            voucherItem.setProduct(item.getProduct());

                            // 设置为销售的单位以及数量
                            voucherItem.setUom(item.getUom());
                            voucherItem.setProductQty(item.getProductUomQty());

                            voucherItem.setOriginItemId(item.getId());
                            voucherItem.setSourceItemId(item.getId());
                            voucherItem.setOwner(purContract.getCompany());

                            Tax tax = taxService.getPurchaseTax(item.getCompany(), item.getSupplier(), item.getProduct());//供应商进项税
                            voucherItem.setTax(tax);
                            voucherItem.setSupplier(item.getSupplier());
                            voucherItem.setPriceUnit(item.getPriceOutUnitInTax());  // 采购价格取带安成本单价
                            voucherItem.setInnerSalePriceUnit(item.getInnerSalePriceUnit());    // 公司间交易价
                            return voucherItem;
                        }).collect(Collectors.toSet()));

        if (purVoucher.getVoucherItems().size() == 0) throw new RuntimeException("生成带安采购凭证时报错，没有采购凭证明细！");
        purVoucher = invoke("voucher.create", MapUtil.mapped(purVoucher));

        changeFrostQty(purVoucher, "零售单生成，代销带安采购凭证");

        return purVoucher;
    }

    /**
     * 经销销售
     *
     * @param purVoucher       采购凭证
     * @param retailOrderItems 代销带安明细
     */
    private void createCrossSaleVoucher(Voucher purVoucher, List<RetailOrderItem> retailOrderItems) {
        RetailOrder retailOrder = retailOrderItems.get(0).getOrder();
        Voucher voucher = new Voucher();
        voucher.setBusinessType(BusinessType.SALE_ORDER);
        ReflectUtil.copy(purVoucher, voucher, "dept", "company", "clerk", "scene", "customerExpand");

        voucher.setPartner(retailOrder.getCompany().getParty().getPartyRoleByType("Customer"));     // 门店公司
        Contract contract = contractService.getContract(voucher.getDept(), voucher.getPartner(), "distribution", "customer", "零售年审业务");  // 寄售合同
        voucher.setContract(contract);

        voucher.setInventoryMode(voucher.getContract().getCooperation().getInventoryMode());     //设置库存模式
        voucher.setAccountingMethod(voucher.getContract().getCooperation().getAccountingMethod());  // 核算方式

        voucher.setSource(purVoucher.getId());
        voucher.setSourceBusinessType(Voucher.class.getSimpleName());
        voucher.setOrigin(retailOrder.getId());
        voucher.setOriginBusinessType(RetailOrder.class.getSimpleName());

        voucher.setVoucherItems(
                retailOrderItems.stream().map(item -> {
                    VoucherItem voucherItem = new VoucherItem();
                    voucherItem.setProduct(item.getProduct());
                    voucherItem.setUom(item.getUom());

                    voucherItem.setProductQty(item.getProductUomQty());
                    voucherItem.setSourceItemId(item.getId());
                    voucherItem.setOriginItemId(item.getId());
                    voucherItem.setDiscount(0d);
                    voucherItem.setTax(voucherItem.getProduct().getTax());
                    voucherItem.setSupplier(purVoucher.getPartner());
                    voucherItem.setOwner(purVoucher.getCompany());

                    voucherItem.setPriceUnit(item.getInnerSalePriceUnit());

                    return voucherItem;
                }).collect(Collectors.toSet()));

        // 添加采购凭证批次以及供应商信息
        voucher.getVoucherItems().forEach(item -> {
            purVoucher.getVoucherItems().forEach(purchaseVoucherItem -> {

                VoucherInventory voucherInventory = voucherInventoryRepository.findByVoucherItem(purchaseVoucherItem).stream()
                        .findAny().orElseThrow(() -> new RuntimeException("找不到批次信息！"));

                if (item.getProduct().getId().equals(voucherInventory.getProduct().getId())) {
                    item.setInventoryBatch(voucherInventory.getInventoryBatch());
                    item.setSupplier(purchaseVoucherItem.getSupplier());
                }
            });
        });

        voucher = invoke("voucher.create", MapUtil.mapped(voucher));
        invoke("invoice.create", MapUtil.mapped(invoke("voucher.flow.invoice", MapUtil.mapped(voucher))));
    }

}
